﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Facebook;

namespace FeedBack {
    public class FileStoryParser : IStoryParser {
        private IEnumerable<string> files;
        private Func<string, Type, object> deserializer;

        public FileStoryParser(IEnumerable<string> files, Func<string, Type, object> deserializer) {
            this.files = files;
            this.deserializer = deserializer;
        }

        public IEnumerable<Facebook.JsonObject> GetStories() {

            var fn = deserializer;

            foreach (var file in files) {
                JsonObject result = null;
                try {
                    result = fn(File.ReadAllText(file), null) as JsonObject;
                }
                catch (Exception e) {
                    Debug.WriteLine(e.Message);
                }

                if (result != null) {
                    var data = result["data"] as JsonArray;

                    foreach (JsonObject story in data) {
                        yield return story;
                    }

                }
                else {
                    String s = File.ReadAllText(file);

                    int offset = 0;
                    List<string> stories = new List<string>();

                    for (; offset >= 0; ) {
                        offset = RecoverStrory(s, offset, stories);
                    }

                    foreach (var json in stories) {
                        JsonObject story = null;
                        try {
                            story = fn(json, null) as JsonObject;
                        }
                        catch (Exception ex) {
                            Debug.WriteLine(ex.Message);
                            continue;
                        }
                        yield return story;
                    }
                }
            }
        }


        private static int RecoverStrory(String s, int offset, List<string> stories) {
            int idPos = s.IndexOf(@"{""id"":""", offset);
            if (idPos < 0) {
                return -1;
            }
            int createdTimePos = s.IndexOf(@",""created_time"":""", idPos);
            if (createdTimePos < 0) {
                return -1;
            }
            else {
                int pair = 0;
                bool isEscaping = false;
                bool isInQuote = false;

                for (int i = offset; i < createdTimePos; i++) {
                    if (s[i] == '{') {
                        if (!isInQuote) {
                            pair++;
                        }
                    }
                    else if (s[i] == '}') {
                        if (!isInQuote) {
                            pair--;
                        }
                    }
                    else if (s[i] == '\\') {
                        if (!isEscaping) {
                            isEscaping = true;
                            continue;
                        }
                    }
                    else if (s[i] == '"') {
                        if (!isInQuote) {
                            isInQuote = true;
                        }
                        else if (!isEscaping) {
                            isInQuote = true;
                        }
                    }

                    if (isEscaping) {
                        isEscaping = false;
                    }
                }
                if (pair == 1) {
                    isEscaping = false;
                    isInQuote = false;
                    int posComma = 0;
                    string story = "";

                    for (int i = createdTimePos + 1; i < s.Length; i++) {
                        if (s[i] == '{') {
                            if (!isInQuote) {
                                pair++;
                            }
                        }
                        else if (s[i] == '}') {
                            if (!isInQuote) {
                                pair--;
                            }
                        }
                        else if (s[i] == ',') {
                            if (!isInQuote) {
                                posComma = i;
                            }
                        }
                        else if (s[i] == '\\') {
                            if (isInQuote && !isEscaping) {
                                isEscaping = true;
                                continue;
                            }
                        }
                        else if (s[i] == '"') {
                            if (!isInQuote) {
                                isInQuote = true;
                            }
                            else if (!isEscaping) {
                                isInQuote = false;
                            }
                        }

                        if (pair == 0) {
                            story = s.Substring(idPos, i - idPos + 1);
                            stories.Add(story);
                            return i + 1;
                        }
                        if (isEscaping) {
                            isEscaping = false;
                        }
                    }

                    char[] closingBraces = new char[pair];
                    for (int i = 0; i < closingBraces.Length; i++) {
                        closingBraces[i] = '}';
                    }

                    story = s.Substring(idPos, posComma - idPos) + new string(closingBraces);
                    stories.Add(story);
                    return s.Length;

                }
                else if (pair < 0) {
                    return createdTimePos + 1;
                }
                else {
                    return -1;
                }
            }
        }
        
    }
}
